home *** CD-ROM | disk | FTP | other *** search
- /* Function definitions for
- BUMP 1.1
- the Beginners Understandable Matrix Package
- for Borland C++
- */
- #include <iostream.h> // for cout
- #include <ctype.h> // for isdigit()
- #include <stdio.h> // for fgets()
- #include <alloc.h> // for coreleft()
- #include <stdlib.h> // for atof()
- #include <conio.h> // for cprintf()
- #include <string.h> // for strlen()
- #include "bump.h"
- extern unsigned _stklen = 64000;
- int vcount = 0;
- ///////////////// The Vector member functions /////////////////////////
-
- Vector::Vector(int anr, int anc, char atemp, int afr, int afc)
- {
- if(anr != 1 && anc != 1){
- cout << "Either the number of rows or the number of columns must be 1.\n";
- return;
- }
- which = vcount++;
- nr = anr;
- nc = anc;
- temp = atemp;
- fr = afr;
- fc = afc;
- lr = fr + nr - 1;
- lc = fc + nc - 1;
- nelem = nr + nc - 1;
- if(nelem < 0 || nelem > 16000){
- cout << nelem << "is an illegal number of elements for a vector.\n";
- return;
- }
- if(nelem == 0)
- v = 0;
- else if((v = new float[nelem]) == 0)
- cout << "Out of memory.\n";
- }
- Vector::Vector(Vector& a)
- {
- int i;
-
- which = vcount++;
- nr = a.nr;
- nc = a.nc;
- temp = a.temp;
- fr = a.fr;
- fc = a.fc;
- lr = a.lr;
- lc = a.lc;
- nelem = a.nelem;
- /* Before the "operator " functions return, they must "destroy" the Temp
- vector they created. But since many are returning Temp, C++ calls this
- function to make a copy of Temp. That call is implicit; the programmer
- does not explicitly do it. After that call, the destructor is called,
- also implicitly, to destroy the original Temp. This copy will then be
- returned. The following device detects that the vector being copied is a
- temporary vector doomed to immediate destruction, so it just captures the
- v array as its own and sets a.v = 0, so that the destructor won't hurt
- it. */
-
- if(a.temp == 'y'){
- v = a.v;
- a.v = 0;
- }
- else{
- if((v = new float[nelem]) == 0){
- cout << "Out of memory trying to create vector" << which <<".\n";
- exit(1);
- }
- for(i = 0; i < nelem; i++)
- v[i] = a.v[i];
- }
- }
- Vector::~Vector()
- {
- if(v != 0 ) delete v;
- }
- // Free heap memory
- void Vector::freeh()
- {
- if(v != 0 ) delete v;
- v = 0;
- }
- int Vector::ReadA(char *filename)
- {
- FILE *fp;
- int i,j,k;
- char s[241],field[30];
-
- if((fp = fopen(filename,"rt")) == 0){
- cerr << "Cannot open " << filename << ".\n";
- return(ERR);
- }
- fgets(s,240,fp);
- j = 0;
- for(i = 0; i < nelem; i++){
- if(getfloat(v[i],fp,s,j) == ERR){
- cerr << "Out of data in " << filename << ".\n";
- break;
- }
- }
- fclose(fp);
- return(OK);
- }
- void Vector::Display(char *title,int width, int decimalPlaces)
- {
- int i, nperline;
- char fmt[20];
-
- if(strlen(title) > 0) printf("\n%s\n", title);
-
- nperline = 79/width;
- sprintf(fmt,"%s%d.%df", "%",width,decimalPlaces);
-
- for(i = 0;i<nelem;i++){
- printf(fmt,v[i]);
- if(i % nperline == nperline - 1) printf("\n");
- }
- }
-
- Vector& Vector::operator = (Vector& a)
- {
- int i;
- int s = (nelem < a.nelem) ? nelem : a.nelem;
-
- for(i = 0; i < s; i++){
- v[i] = a.v[i];
- }
- a.freet();
- return(*this);
- }
- Vector Vector::operator ~ () // Transposition
- {
- int i;
- Vector Temp(nc,nr,'y',fc,fr);
- for(i = 0; i < nelem; i++)
- Temp.v[i] = v[i];
- return(Temp);
- }
- float& Vector::operator [](int i)
- {
-
- if(v==0){
- cerr << "Error: Reference to a deleted vector.\n";
- exit(1);
- }
- if(nc == 1){
- if (fr > i || lr < i){
- cerr << "Illegal vector index: " << i << "\n";
- exit(1);
- }
- return(v[i - fr]);
- }
- else{
- if (fc > i || lc < i){
- cerr << "illegal vector index: " << i << "\n";
- exit(1);
- }
- return(v[i -fc]);
- }
- }
- Vector Vector::operator - (Vector &a)
- {
- int i;
- if(fr != a.fr || lr != a.lr){
- cout << "vector dimensions do not match in + operator.\n";
- }
-
- Vector Temp(nr,nc,'y');
- for(i = 0; i < nelem; i++)
- Temp.v[i] = v[i] - a.v[i];
- freet();
- return (Temp);
- }
- //////////////// Friends of Vector (only) /////////////////////////
- /* operator + and operator - are written differently to illustrate
- the two methods.
- */
- Vector operator + (Vector &a, Vector &b)
- {
- int i;
- if(b.fr != a.fr || b.lr != a.lr){
- cout << "vector dimensions do not match in + operator.\n";
- }
-
- Vector Temp(a.nr,a.nc,'y');
- for(i = 0; i < a.nelem; i++)
- Temp.v[i] = a.v[i] + b.v[i];
- a.freet();
- b.freet();
- return (Temp);
- }
- Vector operator * (float a, Vector &b)
- {
- int i;
-
- Vector Temp(b.nr,b.nc,'y');
- for(i = 0; i < b.nelem; i++)
- Temp.v[i] = a * b.v[i];
- b.freet();
- return (Temp);
- }
- Vector operator / (Vector &a, float b)
- {
- int i;
- float recip;
-
- Vector Temp(a.nr,a.nc,'y');
- recip = 0;
- if(b == 0) printf("Division by zero in Vector operator /.\n");
- else recip = 1./b;
- for(i = 0; i < a.nelem; i++)
- Temp.v[i] = a.v[i]*recip;
-
- a.freet();
- return (Temp);
- }
- ////////////////////// THE MATRIX MEMBER FUNCTIONS /////////////////////////
- Matrix::Matrix(int anr, int anc, char atemp, int afr, int afc)
- {
- int i;
-
- which = vcount++;
- nr = anr;
- nc = anc;
- temp = atemp;
- fr = afr;
- fc = afc;
- lr = fr + nr - 1;
- lc = fc + nc - 1;
- if((m = new float* [nr]) == 0) goto gripe;
- m -= fr;
- for(i = fr; i <= lr; i++){
- if((m[i] = new float [nc]) == 0) goto gripe;
- m[i] -= fc;
- }
- return;
- gripe:
- cout << "Out of memory on array number " << which << ".\n";
- exit(1);
- }
- Matrix::Matrix(Matrix& a)
- {
- int i,j;
- which = vcount++;
- nr = a.nr;
- nc = a.nc;
- temp = a.temp;
- fr = a.fr;
- fc = a.fc;
- lr = a.lr;
- lc = a.lc;
- // See the note at this point in Vector::Vector(Vector& a), which
- // applies here also.
- if(a.temp == 'y'){
- m = a.m;
- a.m = 0;
- }
- else{
- if((m = new float* [nr]) == 0) goto gripe;
- m -= fr;
- for(i = fr; i <= lr; i++){
- if((m[i] = new float [nc]) == 0) goto gripe;
- m[i] -= fc;
- }
- for(i = fr; i <= lr; i++){
- for(j = fc; j <= lc; j++)
- m[i][j] = a.m[i][j];
- }
- }
- return;
- gripe:
- cout << "Out of memory on array number " << which << ".\n";
- exit(1);
- }
- Matrix::~Matrix()
- {
- freeh();
- }
- void Matrix::freeh()
- {
- int i;
-
- if(m == 0) return;
- for(i = fr; i <= lr; i++)
- delete m[i];
- delete m;
- m = 0;
- }
-
- int Matrix::ReadA(char *filename)
- {
- FILE *fp;
- int i,j,k;
- char s[241];
-
- if((fp = fopen(filename,"rt")) == 0){
- cerr << "Cannot open " << filename << ".\n";
- return(ERR);
- }
- fgets(s,240,fp);
- k = 0;
- for(i = fr; i <= lr; i++){
- for(j = fc; j <= lc; j++){
- if(getfloat(m[i][j],fp,s,k) == ERR) break;
- }
- }
- fclose(fp);
- return(OK);
- }
- void Matrix::Display(char *title,int width, int decimalPlaces)
- {
- int i, j, nperline;
- char fmt[20];
-
- if(strlen(title) > 0) printf("\n%s\n", title);
-
- nperline = 79/width;
- sprintf(fmt,"%s%d.%df", "%",width,decimalPlaces);
- for(i = fr; i <= lr; i++){
- for(j = fc; j <= lc; j++){
- printf(fmt,m[i][j]);
- if((j - fc % nperline == nperline -1) && j < lc)
- printf("\n");
- }
- printf("\n");
- }
- }
- Matrix& Matrix::operator = (Matrix& a)
- {
- int i,j,nrmin,ncmin;
- nrmin = nr < a.nr ? nr : a.nr;
- ncmin = nc < a.nc ? nc : a.nc;
-
- if(nr != a.nr || nc != a.nc)
- cout << "Equating matrices of unequal size.\n";
- for(i = 0; i < nrmin; i++){
- for(j = 0; j < ncmin; j++)
- m[fr+i][fc+j] = a.m[a.fr+i][a.fc+j];
- }
- a.freet();
- return(*this);
- }
- Matrix Matrix::operator ~ () //Transposition
- {
- int i,j;
-
- Matrix Temp(nc,nr,'y',fc,fr);
- for(i = fr; i <= lr; i++){
- for(j = fc; j <= lc; j++)
- Temp.m[j][i] = m[i][j];
- }
- return(Temp);
- }
- float * Matrix::operator [](int i)
- {
- if(m==0){
- cerr << "Error: Reference to a deleted matrix.\n";
- exit(1);
- }
-
- if(i < fr || i > lr ){
- cerr << "illegal matrix row index: " << i << "." << "\n";
- cerr << "returning first row. \n";
- return m[fr];
- }
- return(m[i]);
- }
- Matrix Matrix::operator ! () // Inversion
- {
- double determinant;
-
- if(temp == 'n'){
- Matrix Temp(*this);
- Temp.temp = 'y';
- Temp.invert();
- return(Temp);
- }
- else{ // If this matrix is temporary, turn it into its inverse.
- invert();
- return(*this);
- }
- }
- // Turn a matrix into its inverse. The value returned is the determinant.
- double Matrix::invert(int startrow, int endrow)
- {
- double pivot,determinant;
- int i, j, k;
-
- if(startrow == 0) startrow = fr;
- if(endrow == 0) endrow = lr;
- determinant = 1.;
- for(i = startrow; i <= endrow; i++){
- if((pivot = m[i][i])== 0.){
- printf("Zero diagonal; matrix probably singular. Returning partly inverted matrix.\n");
- return(determinant);
- }
- determinant *= pivot;
- m[i][i] = 1.;
- for (j = fc; j <= lc; j++)
- m[i][j] /= pivot;
- for (k = fr; k <= lr; k++){
- if(k == i) continue;
- pivot = m[k][i];
- m[k][i] = 0.;
- for(j = fc; j <= lc; j++)
- m[k][j] -= pivot*m[i][j];
- }
- }
- return(determinant);
- }
- ///////////////FRIENDS OF MATRIX AND VECTOR ////////////////////
- /* M << b stores the vector b into the first column or row
- of the Matrix M. It seems impossible to use = for this
- operation because the compiler insists that "operator ="
- must be member, not merely a friend of the class. Thus it
- is impossible to get at the protected elements of two different
- classes in an "operator =" function. Hence the use of <<.
- */
- void operator << (Matrix& a, Vector& b)
- {
- int i, nrmin, ncmin;
- nrmin = min(a.nr,b.nr);
- ncmin = min(a.nc,b.nc);
- if(a.nr != b.nr || a.nc != b.nc)
- cout << "<< applied to arrays of unequal size.\n";
- if(b.nc == 1){ //The vector is a column
- for(i=0;i<nrmin;i++)
- a.m[a.fr+i][a.fc] = b.v[i];
- }
- else{
- for(i= 0;i<ncmin;i++)
- a.m[a.fr][a.fc+i] = b.v[i];
- }
- b.freet();
- }
-
- Matrix operator + (Matrix &a, Matrix &b)
- {
- int i,j,fr,lr,fc,lc;
- if(b.fr != a.fr || b.lr != a.lr){
- cout << "matrix dimensions do not match in + operator.\n";
- cout << "adding overlapping areas into a matrix with dimensions of the left one.\n";
- }
- fr = max(a.fr,b.fr);
- lr = min(a.lr,b.lr);
- fc = max(a.fc,b.fc);
- lc = min(a.lc,b.lc);
-
- Matrix Temp(a.nr,a.nc,'y');
- for(i = fr; i <= lr; i++){
- for(j = fc; j <= lc; j++)
- Temp.m[i][j] = a.m[i][j] + b.m[i][j];
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Matrix operator - (Matrix &a, Matrix &b)
- {
- int i,j,fr,lr,fc,lc;
- if(b.fr != a.fr || b.lr != a.lr){
- cout << "matrix dimensions do not match in + operator.\n";
- cout << "adding overlapping areas into a matrix with dimensions of the left one.\n";
- }
- fr = max(a.fr,b.fr);
- lr = min(a.lr,b.lr);
- fc = max(a.fc,b.fc);
- lc = min(a.lc,b.lc);
-
- Matrix Temp(a.nr,a.nc,'y');
- for(i = fr; i <= lr; i++){
- for(j = fc; j <= lc; j++)
- Temp.m[i][j] = a.m[i][j] - b.m[i][j];
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Matrix operator * (float a, Matrix& b)
- {
- int i,j,fr,lr,fc,lc;
-
- Matrix Temp(b.nr,b.nc,'y');
- for(i = b.fr; i <= b.lr; i++){
- for(j = b.fc; j <= b.lc; j++)
- Temp.m[i][j] = a*b.m[i][j];
- }
- b.freet();
- return(Temp);
- }
- Matrix operator / (Matrix& a, float b)
- {
- int i,j,fr,lr,fc,lc;
- float recip;
-
- recip = 0;
- if(b != 0) recip = 1./b;
- else {
- printf("Dividing a matrix by 0. Result is 0.\n");
- }
- Matrix Temp(a.nr,a.nc,'y');
- for(i = a.fr; i <= a.lr; i++){
- for(j = a.fc; j <= a.lc; j++)
- Temp.m[i][j] = recip*a.m[i][j];
- }
- a.freet();
- return(Temp);
- }
- Matrix operator * (Matrix &a, Matrix &b)
- {
- int i,j,k,fr,lr,fc,lc;
- double sum;
-
- Matrix Temp(a.nr,b.nc,'y',a.fr,b.fc);
- for(i = a.fr; i <= a.lr; i++){
- for(j = b.fc; j <= b.lc; j++)
- Temp.m[i][j] = 0.;
- }
- if(a.nc != b.nr){
- cout << "matrix dimensions do not match in * operator.\n";
- cout << "returning a zero matrix.\n";
- }
- else {
- for(i = a.fr; i <= a.lr; i++){
- for(j = b.fc; j <= b.lc; j++){
- sum = 0;
- for(k = 0; k < a.nc; k++)
- sum += a.m[i][a.fc+k]*b.m[b.fr+k][j];
- Temp.m[i][j] = sum;
- }
- }
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Vector operator * (Vector& a, Matrix& b)
- {
- int i,j,fr,lr,fc,lc;
- double sum;
-
- Vector Temp(a.nr,b.nc,'y',a.fr,b.fc);
- for(i = 0; i < Temp.nelem; i++){
- Temp.v[i] = 0.;
- }
- if(a.nc != b.nr){
- cout << "vector*matrix dimensions do not match.\n";
- cout << "returning a zero vector.\n";
- }
- else {
- for(i = 0; i < a.nelem; i++){
- sum = 0;
- for(j = 0; j < b.nr ; j++)
- sum += a.v[j]*b.m[b.fr+j][b.fc+i];
- Temp.v[i] = sum;
- }
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Vector operator * (Matrix& a, Vector& b)
- {
- int i,j,fr,lr,fc,lc;
- double sum;
-
- Vector Temp(a.nr,b.nc,'y',a.fr,b.fc);
- for(i = 0; i < Temp.nelem; i++){
- Temp.v[i] = 0.;
- }
- if(a.nc != b.nr){
- cout << "matrix*vector dimensions do not match.\n";
- cout << "returning a zero vector.\n";
- }
- else {
- for(i = 0; i < Temp.nelem; i++){
- sum = 0;
- for(j = 0; j < a.nc; j++)
- sum += a.m[a.fr+i][a.fc+j]*b.v[j];
- Temp.v[i] = sum;
- }
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Matrix operator * (Vector& a, Vector& b)
- {
- int i,j,k,fr,lr,fc,lc;
- double sum;
-
- Matrix Temp(a.nr,b.nc,'y',a.fr,b.fc);
- for(i = a.fr; i <= a.lr; i++){
- for(j = b.fc; j <= b.lc; j++)
- Temp.m[i][j] = 0.;
- }
- if(a.nc != b.nr){
- cout << "vector*vector dimensions do not match.\n";
- cout << "returning a zero matrix.\n";
- }
- else {
- for(i = a.fr; i <= a.lr; i++){
- for(j = b.fc; j <= b.lc; j++){
- sum = 0;
- for(k = 0; k < a.nc; k++)
- sum += a.v[k]*b.v[k];
- Temp.m[i][j] = sum;
- }
- }
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- // A/B gives what is usually written as A'B, but without creating A'.
- Matrix operator / (Matrix& a, Matrix& b)
- {
- int i,j,k,n;
- double sum;
-
- Matrix Temp(a.nc,b.nc,'y',a.fc,b.fc);
-
- if(a.nr != b.nr){
- cerr << "Matrices do not have same number of rows in / operator.\n";
- cerr << "Using the smaller number.\n";
- }
- n = min(a.nr,b.nr);
- for (i = a.fc; i <= a.lc; i++){
- for(j = b.fc; j <= b.lc; j++){
- sum = 0;
- for(k = 0; k < n; k++)
- sum += a.m[a.fr+k][i]*b.m[b.fr+k][j];
- Temp.m[i][j] = sum;
- }
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Vector operator / (Matrix& a, Vector& b)
- {
- int i,j,k,n;
- double sum;
-
- Vector Temp(a.nc,b.nc,'y',a.fc,b.fc);
-
- if(a.nr != b.nr){
- cerr << "Matrices do not have same number of rows in / operator.\n";
- cerr << "Using the smaller number.\n";
- }
- n = min(a.nr,b.nr);
- for (i = a.fc; i <= a.lc; i++){
- sum = 0;
- for(k = 0; k < n; k++)
- sum += a.m[a.fr+k][i]*b.v[k];
- Temp.v[i-a.fc] = sum;
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Vector operator / (Vector& a, Matrix& b)
- {
- int i,j,k,n;
- double sum;
-
- Vector Temp(a.nc,b.nc,'y',a.fc,b.fc);
-
- if(a.nr != b.nr){
- cerr << "Vector and Matrix do not have same number of rows in / operator.\n";
- cerr << "Using the smaller number.\n";
- }
- n = min(a.nr,b.nr);
- for(j = b.fc; j <= b.lc; j++){
- sum = 0;
- for(k = 0; k < n; k++)
- sum += a.v[k]*b.m[b.fr+k][j];
- Temp.v[j-b.fc] = sum;
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- Matrix operator / (Vector& a, Vector& b)
- {
- int i,j,k,n;
- double sum;
-
- Matrix Temp(a.nc,b.nc,'y',a.fc,b.fc);
-
- if(a.nr != b.nr){
- cerr << "Vectors do not have same number of rows in / operator.\n";
- cerr << "Using the smaller number.\n";
- }
- n = min(a.nr,b.nr);
- for (i = a.fc; i <= a.lc; i++){
- for(j = b.fc; j <= b.lc; j++){
- sum = 0;
- for(k = 0; k < n; k++)
- sum += a.v[i-a.fc+k]*b.v[j-b.fc+k];
- Temp.m[i][j] = sum;
- }
- }
- a.freet();
- b.freet();
- return(Temp);
- }
- //////////// Utility Functions ///////////////////////////////////
- int getfloat(float& f, FILE *fp, char *s, int& j)
- {
- int k;
- char field[30];
-
- // skip over non-numerical characters
- search: while(isnum(s[j]) == 0 && s[j] != '\n') j++;
- if(s[j] == '\n'){
- if(fgets(s,240,fp) == NULL){
- return(ERR); // Hit end of file.
- }
- j = 0;
- goto search;
- }
- k = 0;
- while(isnum(s[j+k]) != 0 ){
- field[k] = s[j+k];
- k++;
- }
- field[k] = '\0';
- j += k;
- f = atof(field);
- return(OK);
- }
- // isnum returns 1 if c is a digit, '.', '-', '+'.
- int isnum(char c)
- {
- if (isdigit(c)) return 1;
- if(c == '.' || c == '-' || c == '+' ) return 1;
- return 0;
- }
- int max(int a, int b)
- {
- return(a < b ? b : a);
- }
- int min(int a, int b)
- {
- return(a < b ? a : b);
- }
-